#include "ArgumentsBuilder.h"
#include "ScriptCompiler/ScriptFileContext.h"
#include "ScriptCompiler/Token/Token.h"
#include "ScriptCompiler/ASTBuilder/ExpressionBuilder.h"


CArgumentsBuilder::CArgumentsBuilder(std::shared_ptr<CScriptFileContext> InContext)
{
    Context = InContext;
}

bool CArgumentsBuilder::ReadCurentToken()
{

    //read '('
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type != LeftBracketType)
        {
            Context->RaiseError(10003,Token,U"Expected '('");
            return false;
        }
        LeftBracket = Token;
        Context->CurrentTokenIndex++;
    }

    //find ')'
    uint64_t RightBracketIndex=-1;
    {
        auto RightBracketPos=FindPairedToken(LeftBracketType, RightBracketType, Context);
        if(!RightBracketPos)
        {
            //raise error, require ')'
            Context->RaiseError(10004,Context->GetCurrentToken(),U"Expected paired ')'/'}'/']'/'>' ");
            return false;
        }
        RightBracketIndex=*RightBracketPos;
        RightBracket=Context->GetToken(RightBracketIndex);
    }

    if(RightBracketIndex==Context->CurrentTokenIndex)
    {
        //no arguments
        //skip ')'
        Context->CurrentTokenIndex++;
        return true;
    }

    //read parameters
    int32_t CurrentIndex=Context->CurrentTokenIndex;
    while (true)
    {
        auto Token=Context->GetToken(CurrentIndex);
        if(Token->Type==EScriptTokenType::LeftParentheses)
        {
            //find right Parentheses
            auto RightParentheses= FindPairedParentheses(CurrentIndex+1,Context);
            if(!RightParentheses.HasValue())
            {
                //raise Error
                Context->RaiseError(10005,Token,U"Cant find paired ')'");
                return false;
            }

            CurrentIndex= RightParentheses.GetValue()+1;
            continue;
        }

        if(Token->Type==EScriptTokenType::Less)
        {
            auto RightAngleBracket= FindPairedAngleBracket(
                CurrentIndex+1,Context);
            if(!RightAngleBracket.HasValue())
            {
                //raise Error
                Context->RaiseError(10159,Token,U"Cant find paired '>'");
                return false;
            }

            CurrentIndex= RightAngleBracket.GetValue()+1;
            continue;
        }

        if(Token->Type==EScriptTokenType::LeftBracket)
        {
            auto RightBracket= FindPairedBracket(
                CurrentIndex+1,Context);
            if(!RightBracket.HasValue())
            {
                //raise Error
                Context->RaiseError(10160,Token,U"Cant find paired ']'");
                return false;
            }

            CurrentIndex= RightBracket.GetValue()+1;
            continue;
        }

        if(Token->Type==EScriptTokenType::LeftBrace)
        {
            auto RightBrace=FindPairedBrace(CurrentIndex+1,Context);
            if(!RightBrace.HasValue())
            {
                //raise Error
                Context->RaiseError(10161,Token,U"Cant find paired '}'");
                return false;
            }
            CurrentIndex= RightBrace.GetValue()+1;
            continue;
        }

        if(Token->Type==EScriptTokenType::Comma)
        {
            auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,CurrentIndex);
            if (!ExpressionBuilder->ReadCurentToken())
            {
                return false;
            }
            Result.Add(ExpressionBuilder->Result);

            //skip comma
            assert(Context->CurrentTokenIndex==CurrentIndex);
            Context->CurrentTokenIndex++;
            CurrentIndex++;
            continue;
        }

        if(CurrentIndex==RightBracketIndex)
        {
            auto ExpressionBuilder = std::make_shared<CExpressionBuilder>(Context,RightBracketIndex);
            if (!ExpressionBuilder->ReadCurentToken())
            {
                return false;
            }
            if(ExpressionBuilder->Result->Type!=EASTNodeType::Empty)
            {
                Result.Add(ExpressionBuilder->Result);
            }

            //skip )
            Context->CurrentTokenIndex++;
            return true;
        }

        CurrentIndex++;
    }


}